Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Displaying Raw • Download


electron/main-legacy.js v4.6.0-rc.2 (7bbe9846) Text, 18.78 KB

Tff7b72const Tb4b4b4{
Te6edf3appTb4b4b4,
Te6edf3BrowserWindowTb4b4b4,
Te6edf3dialogTb4b4b4,
Te6edf3ipcMainTb4b4b4,
Te6edf3shellTb4b4b4,
Te6edf3systemPreferencesTb4b4b4,
Te6edf3NotificationTb4b4b4,
Te6edf3powerSaveBlockerTb4b4b4,
Tb4b4b4} Tff7b72= Te6edf3requireTb4b4b4(Ta5d6ff"electron"Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3electronPrompt Tff7b72= Te6edf3requireTb4b4b4(Ta5d6ff"electron-prompt"Tb4b4b4)Tb4b4b4;
Tff7b72const Tb4b4b4{ Te6edf3spawn Tb4b4b4} Tff7b72= Te6edf3requireTb4b4b4(Ta5d6ff"child_process"Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3fs Tff7b72= Te6edf3requireTb4b4b4(Ta5d6ff"fs"Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3path Tff7b72= Te6edf3requireTb4b4b4(Ta5d6ff"node:path"Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3crypto Tff7b72= Te6edf3requireTb4b4b4(Ta5d6ff"crypto"Tb4b4b4)Tb4b4b4;
Tff7b72const Tb4b4b4{ Te6edf3getUserProvidedArguments Tb4b4b4} Tff7b72= Te6edf3requireTb4b4b4(Ta5d6ff"./mainHelpers"Tb4b4b4)Tb4b4b4;
Tff7b72const Tb4b4b4{ Te6edf3isAllowedShellPath Tb4b4b4} Tff7b72= Te6edf3requireTb4b4b4(Ta5d6ff"./shellPathGuard"Tb4b4b4)Tb4b4b4;
Tff7b72const Tb4b4b4{ Te6edf3normalizeExternalUrlForOpen Tb4b4b4} Tff7b72= Te6edf3requireTb4b4b4(Ta5d6ff"./safeExternalUrl"Tb4b4b4)Tb4b4b4;

T8b949e// remember main window
Tff7b72var Te6edf3mainWindow Tff7b72= Tff7b72nullTb4b4b4;

Tff7b72function Te6edf3getDialogParentWindowTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3focused Tff7b72= Te6edf3BrowserWindowTb4b4b4.Te6edf3getFocusedWindowTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3focused Tff7b72&& Tff7b72!Te6edf3focusedTb4b4b4.Te6edf3isDestroyedTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3focusedTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3mainWindow Tff7b72&& Tff7b72!Te6edf3mainWindowTb4b4b4.Te6edf3isDestroyedTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3mainWindowTb4b4b4;
Tb4b4b4}
Tff7b72return Tff7b72nullTb4b4b4;
Tb4b4b4}

T8b949e// power save blocker id
Tff7b72var Te6edf3activePowerSaveBlockerId Tff7b72= Tff7b72nullTb4b4b4;

T8b949e// remember child process for exe so we can kill it when app exits
Tff7b72var Te6edf3exeChildProcess Tff7b72= Tff7b72nullTb4b4b4;

T8b949e// store integrity status
Tff7b72var Te6edf3integrityStatus Tff7b72= Tb4b4b4{
Te6edf3backendTff7b72: Tb4b4b4{ Te6edf3okTff7b72: Tff7b72trueTb4b4b4, Te6edf3issuesTff7b72: Tb4b4b4[Tb4b4b4] Tb4b4b4}Tb4b4b4,
Te6edf3dataTff7b72: Tb4b4b4{ Te6edf3okTff7b72: Tff7b72trueTb4b4b4, Te6edf3issuesTff7b72: Tb4b4b4[Tb4b4b4] Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4;

Tff7b72function Te6edf3verifyBackendIntegrityTb4b4b4(Te6edf3exeDirTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3manifestPath Tff7b72= Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3exeDirTb4b4b4, Ta5d6ff"backend-manifest.json"Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fsTb4b4b4.Te6edf3existsSyncTb4b4b4(Te6edf3manifestPathTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3logTb4b4b4(Ta5d6ff"Backend integrity manifest missing, skipping check."Tb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4{ Te6edf3okTff7b72: Tff7b72trueTb4b4b4, Te6edf3issuesTff7b72: Tb4b4b4[Ta5d6ff"Manifest missing"Tb4b4b4] Tb4b4b4}Tb4b4b4;
Tb4b4b4}

Tff7b72try Tb4b4b4{
Tff7b72const Te6edf3manifest Tff7b72= Tffa657JSONTb4b4b4.Te6edf3parseTb4b4b4(Te6edf3fsTb4b4b4.Te6edf3readFileSyncTb4b4b4(Te6edf3manifestPathTb4b4b4, Ta5d6ff"utf8"Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3issues Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;

Tff7b72const Te6edf3filesToVerify Tff7b72= Te6edf3manifestTb4b4b4.Te6edf3files Tff7b72|| Te6edf3manifestTb4b4b4;
Tff7b72const Te6edf3metadata Tff7b72= Te6edf3manifestTb4b4b4.Te6edf3_metadata Tff7b72|| Tb4b4b4{Tb4b4b4}Tb4b4b4;

Tff7b72for Tb4b4b4(Tff7b72const Tb4b4b4[Te6edf3relPathTb4b4b4, Te6edf3expectedHashTb4b4b4] Tff7b72of Tffa657ObjectTb4b4b4.Te6edf3entriesTb4b4b4(Te6edf3filesToVerifyTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3fullPath Tff7b72= Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3exeDirTb4b4b4, Te6edf3relPathTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fsTb4b4b4.Te6edf3existsSyncTb4b4b4(Te6edf3fullPathTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3issuesTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff`Ta5d6ffMissing: Tffd700${Te6edf3relPathTffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tff7b72continueTb4b4b4;
Tb4b4b4}

Tff7b72const Te6edf3fileBuffer Tff7b72= Te6edf3fsTb4b4b4.Te6edf3readFileSyncTb4b4b4(Te6edf3fullPathTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3actualHash Tff7b72= Te6edf3cryptoTb4b4b4.Te6edf3createHashTb4b4b4(Ta5d6ff"sha256"Tb4b4b4)Tb4b4b4.Te6edf3updateTb4b4b4(Te6edf3fileBufferTb4b4b4)Tb4b4b4.Te6edf3digestTb4b4b4(Ta5d6ff"hex"Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3actualHash Tff7b72!== Te6edf3expectedHashTb4b4b4) Tb4b4b4{
Te6edf3issuesTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff`Ta5d6ffModified: Tffd700${Te6edf3relPathTffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3issuesTb4b4b4.Te6edf3length Tff7b72> T79c0ff0 Tff7b72&& Te6edf3metadataTb4b4b4.Te6edf3date Tff7b72&& Te6edf3metadataTb4b4b4.Te6edf3timeTb4b4b4) Tb4b4b4{
Te6edf3issuesTb4b4b4.Te6edf3unshiftTb4b4b4(Ta5d6ff`Ta5d6ffBackend build timestamp: Tffd700${Te6edf3metadataTb4b4b4.Te6edf3dateTffd700}Ta5d6ff Tffd700${Te6edf3metadataTb4b4b4.Te6edf3timeTffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72return Tb4b4b4{
Te6edf3okTff7b72: Te6edf3issuesTb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4,
Te6edf3issuesTff7b72: Te6edf3issuesTb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3errorTb4b4b4) Tb4b4b4{
Te6edf3logTb4b4b4(Ta5d6ff`Ta5d6ffBackend integrity check failed: Tffd700${Te6edf3errorTb4b4b4.Te6edf3messageTffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4{ Te6edf3okTff7b72: Tff7b72falseTb4b4b4, Te6edf3issuesTff7b72: Tb4b4b4[Te6edf3errorTb4b4b4.Te6edf3messageTb4b4b4] Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

T8b949e// allow fetching app version via ipc
Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"app-version"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72return Te6edf3appTb4b4b4.Te6edf3getVersionTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// allow fetching hardware acceleration status via ipc
Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"is-hardware-acceleration-enabled"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
T8b949e// New in Electron 39, fallback for legacy
Tff7b72if Tb4b4b4(Tff7b72typeof Te6edf3appTb4b4b4.Te6edf3isHardwareAccelerationEnabled Tff7b72=== Ta5d6ff"function"Tb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3appTb4b4b4.Te6edf3isHardwareAccelerationEnabledTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72return Tff7b72trueTb4b4b4; T8b949e// Assume true for older versions
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// allow fetching integrity status
Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"get-integrity-status"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72return Te6edf3integrityStatusTb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// Native Notification IPC
Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"show-notification"Tb4b4b4, Tb4b4b4(Te6edf3eventTb4b4b4, Tb4b4b4{ Te6edf3titleTb4b4b4, Te6edf3bodyTb4b4b4, Te6edf3silent Tb4b4b4}Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3notification Tff7b72= Tff7b72new Te6edf3NotificationTb4b4b4(Tb4b4b4{
Te6edf3titleTff7b72: Te6edf3titleTb4b4b4,
Te6edf3bodyTff7b72: Te6edf3bodyTb4b4b4,
Te6edf3silentTff7b72: Te6edf3silentTb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3notificationTb4b4b4.Te6edf3showTb4b4b4(Tb4b4b4)Tb4b4b4;

Te6edf3notificationTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"click"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3mainWindowTb4b4b4) Tb4b4b4{
Te6edf3mainWindowTb4b4b4.Te6edf3showTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3mainWindowTb4b4b4.Te6edf3focusTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// Power Management IPC
Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"set-power-save-blocker"Tb4b4b4, Tb4b4b4(Te6edf3eventTb4b4b4, Te6edf3enabledTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3enabledTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3activePowerSaveBlockerId Tff7b72=== Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3activePowerSaveBlockerId Tff7b72= Te6edf3powerSaveBlockerTb4b4b4.Te6edf3startTb4b4b4(Ta5d6ff"prevent-app-suspension"Tb4b4b4)Tb4b4b4;
Te6edf3logTb4b4b4(Ta5d6ff"Power save blocker started."Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3activePowerSaveBlockerId Tff7b72!== Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3powerSaveBlockerTb4b4b4.Te6edf3stopTb4b4b4(Te6edf3activePowerSaveBlockerIdTb4b4b4)Tb4b4b4;
Te6edf3activePowerSaveBlockerId Tff7b72= Tff7b72nullTb4b4b4;
Te6edf3logTb4b4b4(Ta5d6ff"Power save blocker stopped."Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72return Te6edf3activePowerSaveBlockerId Tff7b72!== Tff7b72nullTb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// ignore ssl errors
Te6edf3appTb4b4b4.Te6edf3commandLineTb4b4b4.Te6edf3appendSwitchTb4b4b4(Ta5d6ff"ignore-certificate-errors"Tb4b4b4)Tb4b4b4;

T8b949e// add support for showing an alert window via ipc
Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"alert"Tb4b4b4, Tff7b72async Tb4b4b4(Te6edf3eventTb4b4b4, Te6edf3messageTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72return Tff7b72await Te6edf3dialogTb4b4b4.Te6edf3showMessageBoxTb4b4b4(Te6edf3mainWindowTb4b4b4, Tb4b4b4{
Te6edf3messageTff7b72: Te6edf3messageTb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// add support for showing a confirm window via ipc
Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"confirm"Tb4b4b4, Tff7b72async Tb4b4b4(Te6edf3eventTb4b4b4, Te6edf3messageTb4b4b4) Tb4b4b4=> Tb4b4b4{
T8b949e// show confirm dialog
Tff7b72const Te6edf3result Tff7b72= Tff7b72await Te6edf3dialogTb4b4b4.Te6edf3showMessageBoxTb4b4b4(Te6edf3mainWindowTb4b4b4, Tb4b4b4{
Te6edf3typeTff7b72: Ta5d6ff"question"Tb4b4b4,
Te6edf3titleTff7b72: Ta5d6ff"Confirm"Tb4b4b4,
Te6edf3messageTff7b72: Te6edf3messageTb4b4b4,
Te6edf3cancelIdTff7b72: T79c0ff0Tb4b4b4, T8b949e// esc key should press cancel button
Te6edf3defaultIdTff7b72: T79c0ff1Tb4b4b4, T8b949e// enter key should press ok button
Te6edf3buttonsTff7b72: Tb4b4b4[
Ta5d6ff"Cancel"Tb4b4b4, T8b949e// 0
Ta5d6ff"OK"Tb4b4b4, T8b949e// 1
Tb4b4b4]Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// check if user clicked OK
Tff7b72return Te6edf3resultTb4b4b4.Te6edf3response Tff7b72=== T79c0ff1Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// add support for showing a prompt window via ipc
Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"prompt"Tb4b4b4, Tff7b72async Tb4b4b4(Te6edf3eventTb4b4b4, Te6edf3messageTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72return Tff7b72await Te6edf3electronPromptTb4b4b4(Tb4b4b4{
Te6edf3titleTff7b72: Te6edf3messageTb4b4b4,
Te6edf3labelTff7b72: Ta5d6ff""Tb4b4b4,
Te6edf3valueTff7b72: Ta5d6ff""Tb4b4b4,
Te6edf3typeTff7b72: Ta5d6ff"input"Tb4b4b4,
Te6edf3inputAttrsTff7b72: Tb4b4b4{
Te6edf3typeTff7b72: Ta5d6ff"text"Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// allow relaunching app via ipc
Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"relaunch"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3appTb4b4b4.Te6edf3relaunchTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3appTb4b4b4.Te6edf3exitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"relaunch-emergency"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3appTb4b4b4.Te6edf3relaunchTb4b4b4(Tb4b4b4{ Te6edf3argsTff7b72: Te6edf3processTb4b4b4.Te6edf3argvTb4b4b4.Te6edf3sliceTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4.Te6edf3concatTb4b4b4(Tb4b4b4[Ta5d6ff"--emergency"Tb4b4b4]Tb4b4b4) Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3appTb4b4b4.Te6edf3exitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"shutdown"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"get-memory-usage"Tb4b4b4, Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72return Te6edf3processTb4b4b4.Te6edf3getProcessMemoryInfoTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// allow showing a file path in os file manager
Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"showPathInFolder"Tb4b4b4, Tb4b4b4(Te6edf3eventTb4b4b4, Te6edf3targetPathTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3ctx Tff7b72= Tb4b4b4{
Te6edf3appTb4b4b4,
Te6edf3getDefaultStorageDirTb4b4b4,
Te6edf3getDefaultReticulumConfigDirTb4b4b4,
Te6edf3getUserProvidedArgumentsTb4b4b4,
Tb4b4b4}Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3isAllowedShellPathTb4b4b4(Te6edf3targetPathTb4b4b4, Te6edf3ctxTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3warnTb4b4b4(Ta5d6ff"showPathInFolder denied (path outside allowed directories)"Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Te6edf3shellTb4b4b4.Te6edf3showItemInFolderTb4b4b4(Te6edf3targetPathTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"open-path"Tb4b4b4, Tb4b4b4(Te6edf3eventTb4b4b4, Te6edf3targetPathTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3ctx Tff7b72= Tb4b4b4{
Te6edf3appTb4b4b4,
Te6edf3getDefaultStorageDirTb4b4b4,
Te6edf3getDefaultReticulumConfigDirTb4b4b4,
Te6edf3getUserProvidedArgumentsTb4b4b4,
Tb4b4b4}Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3isAllowedShellPathTb4b4b4(Te6edf3targetPathTb4b4b4, Te6edf3ctxTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3consoleTb4b4b4.Te6edf3warnTb4b4b4(Ta5d6ff"open-path denied (path outside allowed directories)"Tb4b4b4)Tb4b4b4;
Tff7b72return Ta5d6ff"Path is not allowed"Tb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3shellTb4b4b4.Te6edf3openPathTb4b4b4(Te6edf3targetPathTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"pick-file"Tb4b4b4, Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3win Tff7b72= Te6edf3getDialogParentWindowTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3winTb4b4b4) Tb4b4b4{
Tff7b72return Tff7b72nullTb4b4b4;
Tb4b4b4}
Tff7b72const Tb4b4b4{ Te6edf3canceledTb4b4b4, Te6edf3filePaths Tb4b4b4} Tff7b72= Tff7b72await Te6edf3dialogTb4b4b4.Te6edf3showOpenDialogTb4b4b4(Te6edf3winTb4b4b4, Tb4b4b4{
Te6edf3propertiesTff7b72: Tb4b4b4[Ta5d6ff"openFile"Tb4b4b4]Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3canceled Tff7b72|| Tff7b72!Te6edf3filePaths Tff7b72|| Te6edf3filePathsTb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72return Tff7b72nullTb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3filePathsTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3ipcMainTb4b4b4.Te6edf3handleTb4b4b4(Ta5d6ff"pick-directory"Tb4b4b4, Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3win Tff7b72= Te6edf3getDialogParentWindowTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3winTb4b4b4) Tb4b4b4{
Tff7b72return Tff7b72nullTb4b4b4;
Tb4b4b4}
Tff7b72const Tb4b4b4{ Te6edf3canceledTb4b4b4, Te6edf3filePaths Tb4b4b4} Tff7b72= Tff7b72await Te6edf3dialogTb4b4b4.Te6edf3showOpenDialogTb4b4b4(Te6edf3winTb4b4b4, Tb4b4b4{
Te6edf3propertiesTff7b72: Tb4b4b4[Ta5d6ff"openDirectory"Tb4b4b4]Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3canceled Tff7b72|| Tff7b72!Te6edf3filePaths Tff7b72|| Te6edf3filePathsTb4b4b4.Te6edf3length Tff7b72=== T79c0ff0Tb4b4b4) Tb4b4b4{
Tff7b72return Tff7b72nullTb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3filePathsTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Tff7b72function Te6edf3logTb4b4b4(Te6edf3messageTb4b4b4) Tb4b4b4{
T8b949e// log to stdout of this process
Te6edf3consoleTb4b4b4.Te6edf3logTb4b4b4(Te6edf3messageTb4b4b4)Tb4b4b4;

T8b949e// make sure main window exists
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3mainWindowTb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}

T8b949e// make sure window is not destroyed
Tff7b72if Tb4b4b4(Te6edf3mainWindowTb4b4b4.Te6edf3isDestroyedTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}

T8b949e// log to web console
Te6edf3mainWindowTb4b4b4.Te6edf3webContentsTb4b4b4.Te6edf3sendTb4b4b4(Ta5d6ff"log"Tb4b4b4, Te6edf3messageTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3getDefaultStorageDirTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// if we are running a windows portable exe, we want to use .reticulum-meshchat in the portable exe dir
T8b949e// e.g if we launch "E:\Some\Path\MeshChat.exe" we want to use "E:\Some\Path\.reticulum-meshchat"
Tff7b72const Te6edf3portableExecutableDir Tff7b72= Te6edf3processTb4b4b4.Te6edf3envTb4b4b4.Te6edf3PORTABLE_EXECUTABLE_DIRTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3processTb4b4b4.Te6edf3platform Tff7b72=== Ta5d6ff"win32" Tff7b72&& Te6edf3portableExecutableDir Tff7b72!= Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3portableExecutableDirTb4b4b4, Ta5d6ff".reticulum-meshchat"Tb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// otherwise, we will fall back to putting the storage dir in the users home directory
T8b949e// e.g: ~/.reticulum-meshchat
Tff7b72return Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3appTb4b4b4.Te6edf3getPathTb4b4b4(Ta5d6ff"home"Tb4b4b4)Tb4b4b4, Ta5d6ff".reticulum-meshchat"Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72function Te6edf3getDefaultReticulumConfigDirTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// if we are running a windows portable exe, we want to use .reticulum in the portable exe dir
T8b949e// e.g if we launch "E:\Some\Path\MeshChat.exe" we want to use "E:\Some\Path\.reticulum"
Tff7b72const Te6edf3portableExecutableDir Tff7b72= Te6edf3processTb4b4b4.Te6edf3envTb4b4b4.Te6edf3PORTABLE_EXECUTABLE_DIRTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3processTb4b4b4.Te6edf3platform Tff7b72=== Ta5d6ff"win32" Tff7b72&& Te6edf3portableExecutableDir Tff7b72!= Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3portableExecutableDirTb4b4b4, Ta5d6ff".reticulum"Tb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// otherwise, we will fall back to using the .reticulum folder in the users home directory
T8b949e// e.g: ~/.reticulum
Tff7b72return Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3appTb4b4b4.Te6edf3getPathTb4b4b4(Ta5d6ff"home"Tb4b4b4)Tb4b4b4, Ta5d6ff".reticulum"Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Te6edf3appTb4b4b4.Te6edf3whenReadyTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3thenTb4b4b4(Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
T8b949e// get arguments passed to application, and remove the provided application path
Tff7b72const Te6edf3ignoredArguments Tff7b72= Tb4b4b4[Ta5d6ff"--no-sandbox"Tb4b4b4, Ta5d6ff"--ozone-platform-hint=auto"Tb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3userProvidedArguments Tff7b72= Te6edf3processTb4b4b4.Te6edf3argvTb4b4b4.Te6edf3sliceTb4b4b4(T79c0ff1Tb4b4b4)Tb4b4b4.Te6edf3filterTb4b4b4(Tb4b4b4(Te6edf3argTb4b4b4) Tb4b4b4=> Tff7b72!Te6edf3ignoredArgumentsTb4b4b4.Te6edf3includesTb4b4b4(Te6edf3argTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3shouldLaunchHeadless Tff7b72= Te6edf3userProvidedArgumentsTb4b4b4.Te6edf3includesTb4b4b4(Ta5d6ff"--headless"Tb4b4b4)Tb4b4b4;

Tff7b72if Tb4b4b4(Tff7b72!Te6edf3shouldLaunchHeadlessTb4b4b4) Tb4b4b4{
T8b949e// create browser window
Te6edf3mainWindow Tff7b72= Tff7b72new Te6edf3BrowserWindowTb4b4b4(Tb4b4b4{
Te6edf3widthTff7b72: T79c0ff1500Tb4b4b4,
Te6edf3heightTff7b72: T79c0ff800Tb4b4b4,
Te6edf3autoHideMenuBarTff7b72: Tff7b72trueTb4b4b4,
Te6edf3webPreferencesTff7b72: Tb4b4b4{
T8b949e// used to inject logging over ipc
Te6edf3preloadTff7b72: Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3__dirnameTb4b4b4, Ta5d6ff"preload.js"Tb4b4b4)Tb4b4b4,
T8b949e// Security: disable node integration in renderer
Te6edf3nodeIntegrationTff7b72: Tff7b72falseTb4b4b4,
T8b949e// Security: enable context isolation (default in Electron 12+)
Te6edf3contextIsolationTff7b72: Tff7b72trueTb4b4b4,
T8b949e// Security: enable sandbox for additional protection
Te6edf3sandboxTff7b72: Tff7b72trueTb4b4b4,
T8b949e// Security: disable remote module (deprecated but explicit)
Te6edf3enableRemoteModuleTff7b72: Tff7b72falseTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3mainWindowTb4b4b4.Te6edf3webContentsTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"before-input-event"Tb4b4b4, Tb4b4b4(Te6edf3eventTb4b4b4, Te6edf3inputTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3inputTb4b4b4.Te6edf3type Tff7b72=== Ta5d6ff"keyDown" Tff7b72&& Te6edf3inputTb4b4b4.Te6edf3key Tff7b72=== Ta5d6ff"F12" Tff7b72&& Tff7b72!Te6edf3mainWindowTb4b4b4.Te6edf3isDestroyedTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3mainWindowTb4b4b4.Te6edf3webContentsTb4b4b4.Te6edf3toggleDevToolsTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3eventTb4b4b4.Te6edf3preventDefaultTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// open external links in default web browser instead of electron
Te6edf3mainWindowTb4b4b4.Te6edf3webContentsTb4b4b4.Te6edf3setWindowOpenHandlerTb4b4b4(Tb4b4b4(Tb4b4b4{ Te6edf3url Tb4b4b4}Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72var Te6edf3shouldShowInNewElectronWindow Tff7b72= Tff7b72falseTb4b4b4;

T8b949e// we want to open call.html in a new electron window
T8b949e// but all other target="_blank" links should open in the system web browser
T8b949e// we don't want /rnode-flasher/index.html to open in electron, otherwise user can't select usb devices...
Tff7b72if Tb4b4b4(
Tb4b4b4(Te6edf3urlTb4b4b4.Te6edf3startsWithTb4b4b4(Ta5d6ff"http://localhost"Tb4b4b4) Tff7b72|| Te6edf3urlTb4b4b4.Te6edf3startsWithTb4b4b4(Ta5d6ff"https://localhost"Tb4b4b4)Tb4b4b4) Tff7b72&&
Te6edf3urlTb4b4b4.Te6edf3includesTb4b4b4(Ta5d6ff"/call.html"Tb4b4b4)
Tb4b4b4) Tb4b4b4{
Te6edf3shouldShowInNewElectronWindow Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4}

T8b949e// we want to open blob urls in a new electron window
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3urlTb4b4b4.Te6edf3startsWithTb4b4b4(Ta5d6ff"blob:"Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3shouldShowInNewElectronWindow Tff7b72= Tff7b72trueTb4b4b4;
Tb4b4b4}

T8b949e// open in new electron window
Tff7b72if Tb4b4b4(Te6edf3shouldShowInNewElectronWindowTb4b4b4) Tb4b4b4{
Tff7b72return Tb4b4b4{
Te6edf3actionTff7b72: Ta5d6ff"allow"Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}

Tff7b72const Te6edf3safe Tff7b72= Te6edf3normalizeExternalUrlForOpenTb4b4b4(Te6edf3urlTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3safeTb4b4b4) Tb4b4b4{
Te6edf3shellTb4b4b4.Te6edf3openExternalTb4b4b4(Te6edf3safeTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72return Tb4b4b4{
Te6edf3actionTff7b72: Ta5d6ff"deny"Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// navigate to loading page
Tff7b72await Te6edf3mainWindowTb4b4b4.Te6edf3loadFileTb4b4b4(Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3__dirnameTb4b4b4, Ta5d6ff"loading.html"Tb4b4b4)Tb4b4b4)Tb4b4b4;

T8b949e// ask mac users for microphone access for audio calls to work
Tff7b72if Tb4b4b4(Te6edf3processTb4b4b4.Te6edf3platform Tff7b72=== Ta5d6ff"darwin"Tb4b4b4) Tb4b4b4{
Tff7b72await Te6edf3systemPreferencesTb4b4b4.Te6edf3askForMediaAccessTb4b4b4(Ta5d6ff"microphone"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

T8b949e// find path to python/cxfreeze executable (setup.py builds ReticulumMeshChatX)
Tff7b72const Te6edf3exeName Tff7b72= Te6edf3processTb4b4b4.Te6edf3platform Tff7b72=== Ta5d6ff"win32" Tff7b72? Ta5d6ff"ReticulumMeshChatX.exe" Tff7b72: Ta5d6ff"ReticulumMeshChatX"Tb4b4b4;

T8b949e// get app path (handles both development and packaged app)
Tff7b72const Te6edf3appPath Tff7b72= Te6edf3appTb4b4b4.Te6edf3getAppPathTb4b4b4(Tb4b4b4)Tb4b4b4;
T8b949e// get resources path (where extraFiles are placed)
Tff7b72const Te6edf3resourcesPath Tff7b72= Te6edf3processTb4b4b4.Te6edf3resourcesPath Tff7b72|| Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3appPathTb4b4b4, Ta5d6ff".."Tb4b4b4, Ta5d6ff".."Tb4b4b4)Tb4b4b4;
Tff7b72var Te6edf3exe Tff7b72= Tff7b72nullTb4b4b4;

T8b949e// when packaged, extraFiles are placed at resources/app/electron/build/exe
T8b949e// when packaged with asar, unpacked files are in app.asar.unpacked/ directory
T8b949e// app.getAppPath() returns the path to app.asar, so unpacked is at the same level
Tff7b72const Te6edf3possiblePaths Tff7b72= Tb4b4b4[
T8b949e// packaged app - extraFiles location (resources/app/electron/build/exe)
Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3resourcesPathTb4b4b4, Ta5d6ff"app"Tb4b4b4, Ta5d6ff"electron"Tb4b4b4, Ta5d6ff"build"Tb4b4b4, Ta5d6ff"exe"Tb4b4b4, Te6edf3exeNameTb4b4b4)Tb4b4b4,
T8b949e// packaged app with asar (unpacked files from asarUnpack)
Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3appPathTb4b4b4, Ta5d6ff".."Tb4b4b4, Ta5d6ff"app.asar.unpacked"Tb4b4b4, Ta5d6ff"build"Tb4b4b4, Ta5d6ff"exe"Tb4b4b4, Te6edf3exeNameTb4b4b4)Tb4b4b4,
T8b949e// packaged app without asar (relative to app path)
Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3appPathTb4b4b4, Ta5d6ff"build"Tb4b4b4, Ta5d6ff"exe"Tb4b4b4, Te6edf3exeNameTb4b4b4)Tb4b4b4,
T8b949e// development mode (relative to electron directory)
Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3__dirnameTb4b4b4, Ta5d6ff"build"Tb4b4b4, Ta5d6ff"exe"Tb4b4b4, Te6edf3exeNameTb4b4b4)Tb4b4b4,
T8b949e// development mode (relative to project root)
Te6edf3pathTb4b4b4.Te6edf3joinTb4b4b4(Te6edf3__dirnameTb4b4b4, Ta5d6ff".."Tb4b4b4, Ta5d6ff"build"Tb4b4b4, Ta5d6ff"exe"Tb4b4b4, Te6edf3exeNameTb4b4b4)Tb4b4b4,
Tb4b4b4]Tb4b4b4;

T8b949e// find the first path that exists
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3possibleExe Tff7b72of Te6edf3possiblePathsTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3fsTb4b4b4.Te6edf3existsSyncTb4b4b4(Te6edf3possibleExeTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3exe Tff7b72= Te6edf3possibleExeTb4b4b4;
Tff7b72breakTb4b4b4;
Tb4b4b4}
Tb4b4b4}

T8b949e// verify executable exists
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3exe Tff7b72|| Tff7b72!Te6edf3fsTb4b4b4.Te6edf3existsSyncTb4b4b4(Te6edf3exeTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3errorMsg Tff7b72= Ta5d6ff`Ta5d6ffCould not find executable: Tffd700${Te6edf3exeNameTffd700}Ta5d6ff\nTa5d6ffChecked paths:Ta5d6ff\nTffd700${Te6edf3possiblePathsTb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff"\n"Tb4b4b4)Tffd700}Ta5d6ff\nTa5d6ff\nTa5d6ffApp path: Tffd700${Te6edf3appPathTffd700}Ta5d6ff\nTa5d6ffResources path: Tffd700${Te6edf3resourcesPathTffd700}Ta5d6ff`Tb4b4b4;
Te6edf3logTb4b4b4(Te6edf3errorMsgTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3mainWindowTb4b4b4) Tb4b4b4{
Tff7b72await Te6edf3dialogTb4b4b4.Te6edf3showMessageBoxTb4b4b4(Te6edf3mainWindowTb4b4b4, Tb4b4b4{
Te6edf3messageTff7b72: Te6edf3errorMsgTb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3appTb4b4b4.Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}

Te6edf3logTb4b4b4(Ta5d6ff`Ta5d6ffFound executable at: Tffd700${Te6edf3exeTffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;

T8b949e// Verify backend integrity before spawning
Tff7b72const Te6edf3exeDir Tff7b72= Te6edf3pathTb4b4b4.Te6edf3dirnameTb4b4b4(Te6edf3exeTb4b4b4)Tb4b4b4;
Te6edf3integrityStatusTb4b4b4.Te6edf3backend Tff7b72= Te6edf3verifyBackendIntegrityTb4b4b4(Te6edf3exeDirTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3integrityStatusTb4b4b4.Te6edf3backendTb4b4b4.Te6edf3okTb4b4b4) Tb4b4b4{
Te6edf3logTb4b4b4(Ta5d6ff`Ta5d6ffINTEGRITY WARNING: Backend tampering detected! Issues: Tffd700${Te6edf3integrityStatusTb4b4b4.Te6edf3backendTb4b4b4.Te6edf3issuesTb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff", "Tb4b4b4)Tffd700}Ta5d6ff`Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72try Tb4b4b4{
T8b949e// arguments we always want to pass in
Tff7b72const Te6edf3requiredArguments Tff7b72= Tb4b4b4[
Ta5d6ff"--headless"Tb4b4b4, T8b949e// reticulum meshchatx usually launches default web browser, we don't want this when using electron
Ta5d6ff"--port"Tb4b4b4,
Ta5d6ff"9337"Tb4b4b4,
T8b949e// '--test-exception-message', 'Test Exception Message', // uncomment to test the crash dialog
Tb4b4b4]Tb4b4b4;

T8b949e// if user didn't provide reticulum config dir, we should provide it
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3userProvidedArgumentsTb4b4b4.Te6edf3includesTb4b4b4(Ta5d6ff"--reticulum-config-dir"Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3requiredArgumentsTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff"--reticulum-config-dir"Tb4b4b4, Te6edf3getDefaultReticulumConfigDirTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// if user didn't provide storage dir, we should provide it
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3userProvidedArgumentsTb4b4b4.Te6edf3includesTb4b4b4(Ta5d6ff"--storage-dir"Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3requiredArgumentsTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff"--storage-dir"Tb4b4b4, Te6edf3getDefaultStorageDirTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// spawn executable
Te6edf3exeChildProcess Tff7b72= Tff7b72await Te6edf3spawnTb4b4b4(Te6edf3exeTb4b4b4, Tb4b4b4[
Tb4b4b4...Te6edf3requiredArgumentsTb4b4b4, T8b949e// always provide required arguments
Tb4b4b4...Te6edf3userProvidedArgumentsTb4b4b4, T8b949e// also include any user provided arguments
Tb4b4b4]Tb4b4b4)Tb4b4b4;

T8b949e// log stdout
Tff7b72var Te6edf3stdoutLines Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Te6edf3exeChildProcessTb4b4b4.Te6edf3stdoutTb4b4b4.Te6edf3setEncodingTb4b4b4(Ta5d6ff"utf8"Tb4b4b4)Tb4b4b4;
Te6edf3exeChildProcessTb4b4b4.Te6edf3stdoutTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"data"Tb4b4b4, Tff7b72function Tb4b4b4(Te6edf3dataTb4b4b4) Tb4b4b4{
T8b949e// log
Te6edf3logTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;

T8b949e// keep track of last 10 stdout lines
Te6edf3stdoutLinesTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3stdoutLinesTb4b4b4.Te6edf3length Tff7b72> T79c0ff10Tb4b4b4) Tb4b4b4{
Te6edf3stdoutLinesTb4b4b4.Te6edf3shiftTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// log stderr
Tff7b72var Te6edf3stderrLines Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Te6edf3exeChildProcessTb4b4b4.Te6edf3stderrTb4b4b4.Te6edf3setEncodingTb4b4b4(Ta5d6ff"utf8"Tb4b4b4)Tb4b4b4;
Te6edf3exeChildProcessTb4b4b4.Te6edf3stderrTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"data"Tb4b4b4, Tff7b72function Tb4b4b4(Te6edf3dataTb4b4b4) Tb4b4b4{
T8b949e// log
Te6edf3logTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;

T8b949e// keep track of last 10 stderr lines
Te6edf3stderrLinesTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3stderrLinesTb4b4b4.Te6edf3length Tff7b72> T79c0ff10Tb4b4b4) Tb4b4b4{
Te6edf3stderrLinesTb4b4b4.Te6edf3shiftTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// log errors
Te6edf3exeChildProcessTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"error"Tb4b4b4, Tff7b72function Tb4b4b4(Te6edf3errorTb4b4b4) Tb4b4b4{
Te6edf3logTb4b4b4(Te6edf3errorTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// quit electron app if exe dies
Te6edf3exeChildProcessTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"exit"Tb4b4b4, Tff7b72async Tff7b72function Tb4b4b4(Te6edf3codeTb4b4b4) Tb4b4b4{
T8b949e// if no exit code provided, we wanted exit to happen, so do nothing
Tff7b72if Tb4b4b4(Te6edf3code Tff7b72== Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}

T8b949e// tell user that Visual C++ redistributable needs to be installed on Windows
Tff7b72if Tb4b4b4(Te6edf3code Tff7b72=== T79c0ff3221225781 Tff7b72&& Te6edf3processTb4b4b4.Te6edf3platform Tff7b72=== Ta5d6ff"win32"Tb4b4b4) Tb4b4b4{
Tff7b72await Te6edf3dialogTb4b4b4.Te6edf3showMessageBoxTb4b4b4(Te6edf3mainWindowTb4b4b4, Tb4b4b4{
Te6edf3messageTff7b72: Ta5d6ff"Microsoft Visual C++ redistributable must be installed to run this application."Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3appTb4b4b4.Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}

T8b949e// show crash log
Tff7b72const Te6edf3stdout Tff7b72= Te6edf3stdoutLinesTb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff""Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3stderr Tff7b72= Te6edf3stderrLinesTb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff""Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3dialogTb4b4b4.Te6edf3showMessageBoxTb4b4b4(Te6edf3mainWindowTb4b4b4, Tb4b4b4{
Te6edf3messageTff7b72: Tb4b4b4[
Ta5d6ff"MeshChat Crashed!"Tb4b4b4,
Ta5d6ff""Tb4b4b4,
Ta5d6ff`Ta5d6ffExit Code: Tffd700${Te6edf3codeTffd700}Ta5d6ff`Tb4b4b4,
Ta5d6ff""Tb4b4b4,
Ta5d6ff`Ta5d6ff----- stdout -----Ta5d6ff`Tb4b4b4,
Ta5d6ff""Tb4b4b4,
Te6edf3stdoutTb4b4b4,
Ta5d6ff`Ta5d6ff----- stderr -----Ta5d6ff`Tb4b4b4,
Ta5d6ff""Tb4b4b4,
Te6edf3stderrTb4b4b4,
Tb4b4b4]Tb4b4b4.Te6edf3joinTb4b4b4(Ta5d6ff"\n"Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;

T8b949e// quit after dismissing error dialog
Te6edf3appTb4b4b4.Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3logTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Tff7b72function Te6edf3quitTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3exeChildProcessTb4b4b4) Tb4b4b4{
Te6edf3appTb4b4b4.Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3exeChildProcessTb4b4b4.Te6edf3exitCode Tff7b72!== Tff7b72null Tff7b72|| Te6edf3exeChildProcessTb4b4b4.Te6edf3signalCode Tff7b72!== Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72try Tb4b4b4{
Te6edf3exeChildProcessTb4b4b4.Te6edf3killTb4b4b4(Ta5d6ff"SIGTERM"Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3logTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{
Te6edf3exeChildProcessTb4b4b4.Te6edf3killTb4b4b4(Ta5d6ff"SIGKILL"Tb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3e2Tb4b4b4) Tb4b4b4{
Te6edf3logTb4b4b4(Te6edf3e2Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3appTb4b4b4.Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72const Te6edf3timeoutMs Tff7b72= T79c0ff5000Tb4b4b4;
Tff7b72const Te6edf3timeout Tff7b72= Te6edf3setTimeoutTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72try Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3exeChildProcess Tff7b72&& Te6edf3exeChildProcessTb4b4b4.Te6edf3exitCode Tff7b72=== Tff7b72null Tff7b72&& Te6edf3exeChildProcessTb4b4b4.Te6edf3signalCode Tff7b72=== Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3exeChildProcessTb4b4b4.Te6edf3killTb4b4b4(Ta5d6ff"SIGKILL"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3logTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3appTb4b4b4.Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4, Te6edf3timeoutMsTb4b4b4)Tb4b4b4;
Te6edf3exeChildProcessTb4b4b4.Te6edf3onceTb4b4b4(Ta5d6ff"exit"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3clearTimeoutTb4b4b4(Te6edf3timeoutTb4b4b4)Tb4b4b4;
Te6edf3appTb4b4b4.Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// quit electron if all windows are closed
Te6edf3appTb4b4b4.Te6edf3onTb4b4b4(Ta5d6ff"window-all-closed"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3quitTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────